home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / fmsdisk / fms.fix < prev    next >
Text File  |  1993-11-21  |  11KB  |  502 lines

  1.  /*
  2.  *  FMS.C
  3.  *
  4.  *  File Disk Device (fmsdisk.device)
  5.  *
  6.  *  Simulates a trackdisk by using a large file to hold the 'blocks'.
  7.  *  Mod - CAS - 7/93: look for ENV:FMSUnit<n> containing path to file,
  8.  *        then fall back to old FMS:Unit<n> as filename if ENV not found
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. void SynchroMsg(UWORD cmd, struct Unit *unit);
  14. void ExtendSize(NDUnit *unit, long offset);
  15. void GetUnitName(int unitnum, char *buf);
  16.  
  17.  
  18. typedef NDev    *NDevP;
  19. typedef IOB    *IOBP;
  20.  
  21. struct Library *SysBase    = NULL;
  22. struct DosLibrary *DOSBase    = NULL;
  23.  
  24. NDev *DevBase    = NULL;
  25. APTR DevSegment = NULL;
  26. PORT *FProc    = NULL;
  27. PORT FPort;
  28.  
  29. extern func_ptr DevVectors[];
  30.  
  31. __saveds NDevP    __asm
  32. Init(register __a0 APTR seg)
  33. {
  34.     NDev *db;
  35.  
  36.     SysBase = (struct Library *)(*(ULONG *)4);
  37.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  38.  
  39.     DevBase = db = (NDev *)MakeLibrary((long **)DevVectors,NULL,NULL,sizeof(NDev),NULL);
  40.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  41.     db->Lib.lib_Node.ln_Name = DeviceName;
  42.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  43.     db->Lib.lib_Version = 1;
  44.     db->Lib.lib_IdString= (APTR)IdString;
  45.  
  46.     DevSegment = seg;
  47.     AddDevice((DEV *)db);
  48.     return(db);
  49. }
  50.  
  51. __saveds NDevP __asm
  52. DevOpen(register __d0 long unitnum,
  53.     register __a1 IOBP iob,
  54.     register __d1 long flags
  55.        )
  56.  
  57. {
  58.     NDev *nd = DevBase;
  59.     NDUnit *unit = &nd->Unit[unitnum];
  60.  
  61.     if (++nd->Lib.lib_OpenCnt == 1) {
  62.     FProc = CreateProc("FMS-Dummy", 0, (long)DUMmySeg >> 2, 4096);
  63.     FPort.mp_SigBit = SIGBREAKB_CTRL_D;    /*  port init */
  64.     FPort.mp_SigTask= FProc->mp_SigTask;
  65.     FPort.mp_Flags = PA_SIGNAL;
  66.     NewList(&FPort.mp_MsgList);
  67.     }
  68.  
  69.     if (++unit->OpenCnt == 1)
  70.     SynchroMsg(CMD_OPENUNIT, unit);
  71.  
  72.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  73.     iob->io_Unit = (struct Unit *)unit;
  74.     iob->io_Error = 0;
  75.     return(nd);
  76. }
  77.  
  78. /*
  79.  *  expunge device, no arguments
  80.  */
  81.  
  82. __saveds APTR
  83. DevExpunge(void)
  84. {
  85.     NDev *nd = DevBase;
  86.     APTR dseg = DevSegment;
  87.  
  88.     if (dseg == NULL)
  89.     Alert(24);
  90.     if (nd->Lib.lib_OpenCnt) {
  91.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  92.     return(NULL);
  93.     }
  94.     Remove((NODE *)nd);
  95.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  96.     ADevExpunge();
  97.     return(dseg);
  98. }
  99.  
  100. /*
  101.  *  device close.  Dummy pointer before iob so iob gets assigned A1
  102.  *
  103.  *    iob:    A1
  104.  */
  105.  
  106. __saveds APTR __asm
  107. DevClose(register __a1 IOBP iob)
  108.  
  109.  
  110. {
  111.     NDev *nd = DevBase;
  112.  
  113.     {
  114.     NDUnit *unit = (NDUnit *)iob->io_Unit;
  115.     if (unit->OpenCnt && --unit->OpenCnt == 0)
  116.         SynchroMsg(CMD_CLOSEUNIT, unit);
  117.     }
  118.  
  119.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  120.     return(NULL);
  121.     if (FProc) {
  122.     SynchroMsg(CMD_KILLPROC, NULL);
  123.     FProc = NULL;
  124.     }
  125.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  126.     return(DevExpunge());
  127.     /*
  128.      *    close down resources
  129.      */
  130.     return(NULL);
  131. }
  132.  
  133. DevCall
  134. APTR
  135. DevReserved(dummyp)
  136. void *dummyp;
  137. {
  138.     return(0);
  139. }
  140.  
  141. __saveds void __asm
  142. DevBeginIO(register __a1 IOBP iob)
  143.  
  144.  
  145.  
  146. {
  147.     /*NDev *nd = DevBase;*/
  148.  
  149.     iob->io_Error = 0;
  150.     iob->io_Actual = 0;
  151.  
  152.     switch(iob->io_Command & ~TDF_EXTCOM) {
  153.     case CMD_INVALID:
  154.     iob->io_Error = IOERR_NOCMD;
  155.     break;
  156.     case CMD_RESET:
  157.     break;
  158.     case CMD_READ:
  159.     PutMsg(&FPort, &iob->io_Message);
  160.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  161.     iob = NULL;
  162.     break;
  163.     case CMD_WRITE:
  164.     PutMsg(&FPort, &iob->io_Message);
  165.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  166.     iob = NULL;
  167.     break;
  168.     case CMD_UPDATE:
  169.     PutMsg(&FPort, &iob->io_Message);
  170.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  171.     iob = NULL;
  172.     break;
  173.     case CMD_CLEAR:
  174.     break;
  175.     case CMD_STOP:
  176.     break;
  177.     case CMD_START:
  178.     break;
  179.     case CMD_FLUSH:
  180.     break;
  181.     case TD_MOTOR:        /*    motor,    no action   */
  182.     case TD_SEEK:        /*    seek,    no action   */
  183.     break;
  184.     case TD_FORMAT:        /*    format            */
  185.     PutMsg(&FPort, &iob->io_Message);
  186.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  187.     iob = NULL;
  188.     break;
  189.     case TD_REMOVE:        /*    not supported        */
  190.     iob->io_Error = IOERR_NOCMD;
  191.     break;
  192.     case TD_CHANGENUM:        /*    change count never changes  */
  193.     iob->io_Actual = 1;
  194.     break;
  195.     case TD_CHANGESTATE:    /*    0=disk in drive     */
  196.     iob->io_Actual = 0;
  197.     break;
  198.     case TD_PROTSTATUS:     /*    io_Actual -> 0 (rw) */
  199.     iob->io_Actual = 0;
  200.     break;
  201.     case TD_RAWREAD:        /*    not supported        */
  202.     case TD_RAWWRITE:
  203.     iob->io_Error = IOERR_NOCMD;
  204.     break;
  205.     case TD_GETDRIVETYPE:   /*    drive type?        */
  206.     iob->io_Actual = 0;
  207.     break;
  208.     case TD_GETNUMTRACKS:
  209.     iob->io_Actual = 0; /*    # of tracks?        */
  210.     break;
  211.     case TD_ADDCHANGEINT:   /*    action never taken  */
  212.     case TD_REMCHANGEINT:
  213.     break;
  214.     default:
  215.     iob->io_Error = IOERR_NOCMD;
  216.     break;
  217.     }
  218.     if (iob) {
  219.     if ((iob->io_Flags & IOF_QUICK) == 0)
  220.         ReplyMsg((MSG *)iob);
  221.     }
  222. }
  223.  
  224. __saveds void __asm
  225. DevAbortIO(register __a1 IOBP iob)
  226. {
  227.     /*NDev *nd = DevBase;*/
  228. }
  229.  
  230. func_ptr DevVectors[] = {
  231.     (func_ptr)DevOpen,
  232.     (func_ptr)DevClose,
  233.     (func_ptr)DevExpunge,
  234.     NULL,
  235.     (func_ptr)DevBeginIO,
  236.     (func_ptr)DevAbortIO,
  237.     (func_ptr)-1
  238. };
  239.  
  240. /*
  241.  *  Server communications
  242.  */
  243.  
  244. void
  245. SynchroMsg(UWORD cmd, struct Unit *unit)
  246. {
  247.     IOB Iob;
  248.  
  249.     do {
  250.     Iob.io_Message.mn_ReplyPort = CreatePort(NULL, 0);
  251.     Iob.io_Command = cmd;
  252.     Iob.io_Unit = unit;
  253.     } while (Iob.io_Message.mn_ReplyPort == NULL);
  254.  
  255.     PutMsg(&FPort, &Iob.io_Message);
  256.     WaitPort(Iob.io_Message.mn_ReplyPort);
  257.     DeletePort(Iob.io_Message.mn_ReplyPort);
  258. }
  259.  
  260. /*
  261.  *    SERVER SIDE (IS A PROCESS)
  262.  *
  263.  *    File name is:
  264.  */
  265.  
  266. __saveds void
  267. CoProc(void)
  268. {
  269.     IOB *iob;
  270.     NDUnit *unit;
  271.     char buf[128];
  272.     char notdone = 1;
  273. #ifdef DEBUG
  274.     long fh = Open("con:0/0/320/100/Debug", 1006);
  275. #endif
  276.  
  277.     Wait(SIGBREAKF_CTRL_D);     /*  wait for port init  */
  278.  
  279.     while (notdone) {
  280.     WaitPort(&FPort);
  281.     while (iob = (IOB *)GetMsg(&FPort)) {
  282.         unit = (NDUnit *)iob->io_Unit;
  283.  
  284. #ifdef DEBUG
  285.         if (DbFH) {
  286.             sprintf(buf, "Cmd %08lx/%04x @ %08lx Buf %08lx %04x\n",
  287.             unit, iob->io_Command, iob->io_Offset, iob->io_Data, iob->io_Length
  288.             );
  289.             Write(DbFH, buf, strlen(buf));
  290.         }
  291. #endif
  292.         /*
  293.          *    cache (increase OFS throughput)
  294.          */
  295.  
  296.         if (CacheLen && (iob->io_Command & ~TDF_EXTCOM) != CMD_WRITE)
  297.         FlushCache();
  298.  
  299.         switch(iob->io_Command & ~TDF_EXTCOM) {
  300.         case CMD_OPENUNIT:
  301.         GetUnitName(unit - &DevBase->Unit[0], buf);
  302.         unit->Fh = Open(buf, 1005);
  303.         if (unit->Fh == NULL) {
  304.             unit->Fh = Open(buf, 1006);
  305.             unit->Extended = 1;
  306.         }
  307. #ifdef DEBUG
  308.         if (DbFH) {
  309.             Write(DbFH, "OPEN ", 5);
  310.             Write(DbFH, buf, strlen(buf));
  311.             Write(DbFH, "\n", 1);
  312.         }
  313. #endif
  314.         if (unit->Fh) {
  315.             Seek(unit->Fh, 0L, 1);
  316.             unit->Size = Seek(unit->Fh, 0L, -1);
  317.         }
  318.         unit->Pos = -1;
  319.         break;
  320.         case CMD_CLOSEUNIT:
  321.         if (unit->Fh) {
  322.             Close(unit->Fh);
  323.             unit->Fh = NULL;
  324.         }
  325.         break;
  326.         case CMD_KILLPROC:
  327.         notdone = 0;
  328.         break;
  329.         case CMD_READ:
  330.         if (unit->Fh == NULL)
  331.             break;
  332.         if (iob->io_Offset + iob->io_Length > unit->Size)
  333.             ExtendSize(unit, iob->io_Offset + iob->io_Length);
  334.         if (unit->Pos != iob->io_Offset)
  335.             Seek(unit->Fh, iob->io_Offset, -1);
  336.         iob->io_Actual = Read(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  337.         if (iob->io_Actual == iob->io_Length)
  338.             unit->Pos = iob->io_Offset + iob->io_Actual;
  339.         else
  340.             unit->Pos = -1;
  341.         break;
  342.         case CMD_WRITE:
  343.         /*
  344.          *  This causes file to be closed/reopened after
  345.          *  formatting.
  346.          */
  347.         if (unit->Extended && unit->Fh) {
  348.             FlushCache();
  349.             Close(unit->Fh);
  350.             GetUnitName(unit - &DevBase->Unit[0], buf);
  351.             unit->Fh = Open(buf, 1005);
  352.             unit->Extended = 0;
  353.         }
  354.         /* fall through */
  355.         case TD_FORMAT:
  356.         if (unit->Fh == NULL)
  357.             break;
  358.  
  359.         if (iob->io_Offset > unit->Size) {
  360.             FlushCache();
  361.             ExtendSize(unit, iob->io_Offset);
  362.         }
  363.         if (CacheUnit != unit) {
  364.             FlushCache();
  365.             CacheUnit = unit;
  366.         }
  367.         if (unit->Pos != iob->io_Offset) {
  368.  
  369.             /*
  370.              *    Handle case where a CMD_WRITE modifies a previously
  371.              *    cached write (occurs with OFS *a lot*)
  372.              */
  373.  
  374.             if (CacheLen) {
  375.             long ci = CacheLen - (unit->Pos - iob->io_Offset);
  376.             if (ci >= 0 && ci + iob->io_Length <= CacheLen) {
  377. #ifdef DEBUG
  378.                 if (DbFH)
  379.                 Write(DbFH, "XBACK\n", 5);
  380. #endif
  381.                 iob->io_Actual = iob->io_Length;
  382.                 movmem(iob->io_Data, CacheBuf + ci, iob->io_Length);
  383.                 break;
  384.             }
  385.             }
  386.             FlushCache();
  387.             Seek(unit->Fh, iob->io_Offset, -1);
  388.         }
  389.  
  390.         if (CacheLen + iob->io_Length > sizeof(CacheBuf))
  391.             FlushCache();
  392.         if (CacheLen + iob->io_Length <= sizeof(CacheBuf)) {
  393.             iob->io_Actual = iob->io_Length;
  394.             unit->Pos = iob->io_Offset + iob->io_Actual;
  395.             movmem(iob->io_Data, CacheBuf + CacheLen, iob->io_Actual);
  396.             CacheLen += iob->io_Actual;
  397.         } else {
  398.             if (CacheLen)
  399.             FlushCache();
  400.             iob->io_Actual = Write(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  401.             if (iob->io_Actual == iob->io_Length)
  402.             unit->Pos = iob->io_Offset + iob->io_Actual;
  403.             else
  404.             unit->Pos = -1;
  405.         }
  406.         break;
  407.         default:
  408.         break;
  409.         }
  410.  
  411.         if (notdone == 0)       /*  forbid before falling through */
  412.         Forbid();           /*  and esp before replying       */
  413.         ReplyMsg(&iob->io_Message);
  414.     }
  415. #ifdef DEBUG
  416.     if (DbFH == NULL)
  417.         DbFH = Open("con:0/0/320/100/Debug", 1006);
  418. #endif
  419.     }
  420. #ifdef DEBUG
  421.     if (DbFH)
  422.     Close(DbFH);
  423. #endif
  424.     /* fall through to exit */
  425. }
  426.  
  427. void
  428. GetUnitName(int unitnum, char *buf)
  429. {
  430. BPTR envfile;
  431. LONG envlen;
  432. BOOL gotit = FALSE;
  433.  
  434. /* New - see if ENVIRONMENT variable FMSUnit<n> exists (ex. FMSUnit2)
  435.  * containing full path to file.
  436.  */
  437. sprintf(buf,"ENV:FMSUnit%d",unitnum);
  438. if(envfile = Open(buf,MODE_OLDFILE))
  439.     {
  440.     envlen = Read(envfile,buf,128-2);
  441.     if(envlen >= 0)
  442.     {
  443.     gotit = TRUE;
  444.     buf[envlen] = '\0';
  445.         if(buf[envlen-1]=='\n') buf[envlen-1] = '\n';
  446.     }
  447.     Close(envfile);
  448.     }
  449. /* Fallback to old FMS:Unit<n> name */
  450. if(!gotit)
  451.     {
  452.     sprintf(buf, "FMS:Unit%d", unitnum);
  453.     }
  454. }
  455.  
  456. /*
  457.  *  Extend the file size in 4K chunks
  458.  */
  459.  
  460. void
  461. ExtendSize(NDUnit *unit, long offset)
  462.  
  463.  
  464. {
  465.     long pos;
  466.     char *buf = AllocMem(EXT_CHUNK, MEMF_CLEAR|MEMF_PUBLIC);
  467.  
  468.     if (buf) {
  469.     if (unit->Extended == 0)
  470.         unit->Extended = 1;
  471.     Seek(unit->Fh, 0L, 1);
  472.     pos = Seek(unit->Fh, 0L, 0);
  473.     while (pos < offset) {
  474.         if (Write(unit->Fh, buf, EXT_CHUNK) != EXT_CHUNK)
  475.         break;
  476.         pos += EXT_CHUNK;
  477.     }
  478.     FreeMem(buf, EXT_CHUNK);
  479.     unit->Pos = -1;     /*    unknown */
  480.     }
  481. }
  482.  
  483. /*
  484.  *  flush sequential write cache
  485.  */
  486.  
  487. void
  488. FlushCache()
  489. {
  490.     NDUnit *unit = CacheUnit;
  491.  
  492. #ifdef DEBUG
  493.     if (DbFH)
  494.     Write(DbFH, "FLUSH\n", 6);
  495. #endif
  496.  
  497.     if (CacheLen) {
  498.     Write(unit->Fh, CacheBuf, CacheLen);
  499.     CacheLen = 0;
  500.     }
  501. }
  502.